package com.groupbuying.payconsumer.mq;

import com.alipay.api.response.AlipayTradeQueryResponse;
import com.aliyun.openservices.ons.api.Consumer;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.Producer;
import com.aliyun.openservices.shade.com.alibaba.fastjson.JSON;
import com.aliyun.openservices.shade.com.alibaba.fastjson.serializer.SerializerFeature;
import com.groupbuying.payconsumer.alipay.AliPay;
import com.groupbuying.payconsumer.alipay.AliPayNativeConstants;
import com.groupbuying.payconsumer.connector.OrderFeign;
import com.groupbuying.payconsumer.connector.SysconfigFeign;
import com.groupbuying.payconsumer.constants.CommonConstants;
import com.groupbuying.payconsumer.constants.PayInfoEnumConstants;
import com.groupbuying.payconsumer.dao.PayAlipayResultDao;
import com.groupbuying.payconsumer.domain.PayInfoDO;
import com.groupbuying.payconsumer.domain.PayOrderRelDO;
import com.groupbuying.payconsumer.service.PayInfoService;
import com.groupbuying.payconsumer.service.PayOrderRelService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 支付宝，支付主动查询逻辑处理类
 *
 * @auther lisurilige
 * @date 2019/8/27
 */
@Component
public class AliPayOrderStateConfirm {

    Logger LOGGER = LoggerFactory.getLogger(AliPayOrderStateConfirm.class);

    @Autowired
    private SysconfigFeign sysconfigFeign;
    @Autowired
    private OrderFeign orderFeign;
    @Autowired
    private PayOrderRelService payOrderRelService;
    @Autowired
    private PayInfoService payInfoService;
//    @Autowired
//    private PayAlipayResultDao payAlipayResultDao;

    @Autowired
    private Producer producer;


    public boolean dealResult(Map<String, Object> resultParam) {

        //1.判断是否第三方单号是否为空
        String dealNo = resultParam.get("key") == null ? "" : resultParam.get("key").toString();
        if (StringUtils.isEmpty(dealNo)) {
            LOGGER.error("第三方交易单号不存在");
            return false;
        }

        LOGGER.info("=====支付宝原生支付，支付结果主动查询开始 第三方交易单号：{}", dealNo);
        try {
            //2.1 查询支付订单支付状态是否已经成功
            PayOrderRelDO payOrderRelDO = payOrderRelService.getByOutTradeNo(dealNo);
            PayInfoDO payInfoDO = payInfoService.get(payOrderRelDO.getId());
            //支付单已经支付完成
            if (PayInfoEnumConstants.ENUM_PAYSTATE_SUCPAY.equals(payInfoDO.getPayState())) {
                LOGGER.info("本地支付单已经是支付完成状态:{}", payInfoDO.getId());
                return true;
            }

            //2.2 组装支付宝请求参数，发送请求，查询单据信息
            //支付宝公共请求参数
            Map<String, String> initParam = sysconfigFeign.getByAppliName(AliPayNativeConstants.APPLICATION_NAME);

            //支付宝查询请求参数
            Map<String, String> param = new HashMap<>();
            param.put("outTradeNo", payOrderRelDO.getOutTradeNo());

            LOGGER.info("========= 开始请求原生支付宝支付=====");
            //TODO  调用支付宝查询订单接口查询支付状态
            AlipayTradeQueryResponse response = AliPay.aliPayQuery(param, initParam);
            LOGGER.info("========= 结束请求原生支付宝支付=====结果：{}", response);

            //支付宝返回结果
            String status = response.getTradeStatus();      //交易状态
            String totalAmt = response.getTotalAmount();    //总金额
            String tradeNo = response.getTradeNo();     //支付宝流水号

            //如果可以查询不到第三方有此订单
            if (response == null) {
                LOGGER.error("第三方支付订单outTradeNo:{},支付单号:{},第三方无此订单", dealNo, tradeNo);
                return true;
            }

            //如果查询结果不是交易成功
            if (!"success".equalsIgnoreCase(status)) {
                LOGGER.info("支付宝，第三方支付订单outTradeNo：{},查询结果为:{}", dealNo, status);
                return false;
            }

            //2.3 签名验证

            //2.6 判断回执金额和支付单金额不一致
            if (payInfoDO.getPayMoney().compareTo(new BigDecimal(totalAmt)) != 0) {
                //TODO 金额不一致对应的处理（作为异常订单处理），暂时记录日志，然后标记消费
                //TODO 发送订单中心冻结交（或许）
                LOGGER.info("第三方单号：{}，支付宝内部单号：{}，错误提示：{}", dealNo, tradeNo, "支付宝交易金额不一致");
                return true;
            }

//            //2.5 保存支付宝返回信息
//            PayAlipayResultDO payAlipayResultDO = new PayAlipayResultDO();
//            payAlipayResultDO.setId(result.get("out_trade_no").toString());
//            payAlipayResultDO.setResultCode(result.get("trade_status").toString());
//            payAlipayResultDO.setTotalAmount(new BigDecimal(result.get("total_amount").toString()));//支付金额
//            payAlipayResultDO.setTradeNo(result.get("trade_no").toString());
//            payAlipayResultDO.setGmtCreate(new Date());
//            //TODO 支付宝请求没有此时间(付款时间)
//            payAlipayResultDO.setGmtPayment(payInfoDO.getGmtCreate());
//            payAlipayResultDO.setGmtModified(new Date());
//            payAlipayResultDO.setIsDelete(PayAlipayResultEnumConstants.ENUM_ISDELETE_UNDEL);
//
//            try {
//                payAlipayResultDao.save(payAlipayResultDO);
//            } catch (DuplicateKeyException exception) {
//                //主键冲突之后，更新
//                payAlipayResultDao.update(payAlipayResultDO);
//                LOGGER.info("订单号：{}，支付宝内部单号：{}，错误提示：{}",
//                        payAlipayResultDO.getId(), payAlipayResultDO.getTradeNo(), "支付宝交易已经保存过了是多次请求，只执行更新");
//            }

            //2.6 订单状态并修改其状态
//            if (PayAlipayResultEnumConstants.ENUM_RESULTCODE_SUCCESS.equals(payAlipayResultDO.getResultCode())) {
//                //查看当前支付单是否已经修改成功
//                if (PayInfoEnumConstants.ENUM_PAYSTATE_SUCPAY.equals(payInfoDO.getPayState())) {
//                    return true;
//                }

            payInfoDO.setPayState(PayInfoEnumConstants.ENUM_PAYSTATE_SUCPAY);
            payInfoDO.setGmtModified(new Date());
            try {
                payInfoService.update(payInfoDO);
                LOGGER.info("第三方单号：{}，支付宝内部单号：{}，状态：{},提示信息：{}", dealNo, tradeNo, status, "成功更新定单信息");
            } catch (Exception e) {
                LOGGER.error("第三方单号：{}，支付宝内部单号：{}，状态：{},提示信息：{}", dealNo, tradeNo, status, "更新订单信息错误");
                return false;
            }
//            } else {
//                LOGGER.info("第三方单号：{}，支付宝内部单号：{}，状态：{}，错误提示：{}",
//                        dealNo,payAlipayResultDO.getId(), payAlipayResultDO.getTradeNo(),
//                        payAlipayResultDO.getResultCode(), "支付宝支付交易失败");
//                return true;
//            }

            //3 订单操作
            //获取订单信息
            Map orderMap = orderFeign.getOrderForPay(payOrderRelDO.getOrderId());
            //订单是否属于够样优店
            boolean curNotify = orderMap.get("orderId").toString().substring(4, 7).equals("000");
            //3.1 商户优惠规则
            if (curNotify) {
                Map ruleMap = new HashMap();
                ruleMap.put("ruleId", orderMap.get("opxRuleId"));
                ruleMap.put("delFlag", CommonConstants.COMMON_FLAG_UNDEL);
                Map rulesMap = sysconfigFeign.getStoreOpexRule(ruleMap);
                orderMap.putAll(rulesMap);

            }

            //3.2 设置订单中心消息传递消息体
            Map<String, Object> orderParam = new HashMap<>();
            orderParam.put("orderId", orderMap.get("orderId"));
            //设置积分中心消息传递消息体
            Map<String, Object> currencyParam = new HashMap<String, Object>();
            if (curNotify) {
                currencyParam.put("payId", payInfoDO.getId());
                currencyParam.put("customerId", orderMap.get("customerId"));
                currencyParam.put("consumptionAmount", orderMap.get("orderPrice"));
                currencyParam.put("backCurrencyRatio", orderMap.get("backCurrencyRatio"));
            }
            //3.3 设置分账中心消息传递内容
            Map<String, Object> settleParam = new HashMap<>();
            settleParam.put("orderId", orderMap.get("orderId"));
            settleParam.put("outTradeNo", payOrderRelDO.getOutTradeNo());
            settleParam.put("ruleId", orderMap.get("opxRuleId"));
            settleParam.put("totalAmount", payInfoDO.getPayMoney());
            //收银台ID
            settleParam.put("counterId", orderMap.get("counterId"));
            //用户ID
            settleParam.put("customerId", orderMap.get("customerId"));
            //
            //支付分账
            settleParam.put("settleType", "0");
            settleParam.put("payType", payInfoDO.getPayType());
            settleParam.put("payChannel", payInfoDO.getPayChannel());

            //4 发送mq
            try {
                //订单中心
                Message orderMessage = new Message(PayMQConfig.ORDER_TOPIC, PayMQConfig.ORDER_TAG_PAY,
                        JSON.toJSONString(orderParam, SerializerFeature.DisableCircularReferenceDetect).getBytes());
                producer.send(orderMessage);
                LOGGER.info("支付单号" + payInfoDO.getId() + "第三方交易单号：" + dealNo + "同步发送订单中心执行完成");
            } catch (Exception e) {
                e.printStackTrace();
                //发送不成功的话，稍后重试

            }
            if (curNotify) {
                try {
                    //积分中心
                    Message currencyMessage = new Message(PayMQConfig.CURRENCY_TOPIC, PayMQConfig.CURRENCY_TAG_ADD,
                            JSON.toJSONString(currencyParam, SerializerFeature.DisableCircularReferenceDetect).getBytes());
                    producer.send(currencyMessage);
                    LOGGER.info("支付单号" + payInfoDO.getId() + "第三方交易单号：" + dealNo + "同步发送积分中心执行完成");
                } catch (Exception e) {
                    e.printStackTrace();
                    //发送不成功的话，稍后重试
                }
            }
            try {
                //分账中心
                Message settleMessage = new Message(PayMQConfig.SETTLE_TOPIC, PayMQConfig.SETTLE_TAG_SPLIT,
                        JSON.toJSONString(settleParam, SerializerFeature.DisableCircularReferenceDetect).getBytes());
                producer.send(settleMessage);
                LOGGER.info("支付单号" + payInfoDO.getId() + "第三方交易单号：" + dealNo + "同步发送分账中心执行完成");
            } catch (Exception e) {
//                        LOGGER.error("订单号：" + payYsResultDO.getId() + "，银盛内部单号：" + payYsResultDO.getTradeNo() + "，发送分账中心失败");
                e.printStackTrace();
                //发送不成功的话，稍后重试
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return true;
    }
}
